package com.feng.seata.service;

import com.feng.seata.mapper.ProductMapper;
import com.feng.seata.tcc.action.IStockTccAction;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;

/**
 *
 * 通过注解开启@TwoPhaseBusinessAction(useTCCFence = true)  解决幂等、悬挂和空回滚问题
 *
 * @author yinglong.zhang
 * @description
 * @date 2024-1-30 17:17
 */
@Slf4j
@Service
public class StockServiceImpl implements IStockTccAction {

    @Resource
    private ProductMapper productMapper;

    @Override
    public boolean prepareDeductStock(BusinessActionContext businessActionContext, Long productId, Integer buyNum) {
        // 预扣库存
       // 相关sql： update stock_tcc_tbl set count = count - #{count,jdbcType=INTEGER}, pre_deduct_count = pre_deduct_count + #{count,jdbcType=INTEGER} where commodity_code = #{commodityCode,jdbcType=VARCHAR} and count <![CDATA[ >= ]]> #{count,jdbcType=INTEGER}
        boolean result = productMapper.prepareDeductStock(productId, buyNum) > 0;
        log.info("预扣库存:{}", result);
        return result;
    }

    @Override
    public boolean commitDeductStock(BusinessActionContext businessActionContext) {
        //TODO 如果在这里出现异常,会一直重试
        Map<String, Object> actionContext = businessActionContext.getActionContext();
        Object productIdObj = actionContext.get("productId");
        Long productId = Long.valueOf(productIdObj.toString()) ;
        Object buyNumObj = actionContext.get("buyNum");
        Integer count = Integer.valueOf(buyNumObj.toString());
        // 执行提交操作，扣除预扣库存
        boolean result = productMapper.commitDeductStock(productId, count) > 0;
        log.info("执行提交操作，扣除预扣库存:{}", result);
        return result;
    }

    @Override
    public boolean rollbackDeductStock(BusinessActionContext businessActionContext) {
        //TODO 如果在这里出现异常,会一直重试
        // 执行回滚
        Map<String, Object> actionContext = businessActionContext.getActionContext();
        Object productIdObj = actionContext.get("productId");
        Long productId = Long.valueOf(productIdObj.toString()) ;
        Object buyNumObj = actionContext.get("buyNum");
        Integer count = Integer.valueOf(buyNumObj.toString());
        boolean result = productMapper.rollbackDeductStock(productId, count) > 0;
        log.info("执行回滚操作，将预扣库存重入库存:{}", result);
        return result;
    }
}
